﻿using System;
using System.Net;
using System.Text.RegularExpressions;
using System.IO;
using System.Collections.Generic;

using System.Web;
using System.Web.Services;

namespace SilverlightFTP.Web
{
    /// <summary>
    /// Summary description for FTPWebService
    /// </summary>
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    // To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line. 
    // [System.Web.Script.Services.ScriptService]
    public class FTPWebService : System.Web.Services.WebService
    {

        [WebMethod]
        public List<FsItem> ListDirectory(string hostdestination, string user, string password)
        {
            hostdestination = hostdestination.Replace('\\', '/');
            hostdestination = hostdestination.TrimEnd(new char[] { '/' });
            string[] month = new string[] { "jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec" };
            FtpWebRequest req = (FtpWebRequest)FtpWebRequest.Create(hostdestination);
            req.Credentials = new NetworkCredential(user, password);
            req.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
            req.Timeout = 10000;
            StreamReader reader;
            try
            {
                reader = new StreamReader(req.GetResponse().GetResponseStream());
            }
            catch(WebException e)
            {
                List<FsItem> errors = new List<FsItem>();
                if (e.Status == WebExceptionStatus.NameResolutionFailure)
                {
                    errors.Add(new FsItem("NameResolutionFailure", "", false, -1));
                }
                if (e.Status == WebExceptionStatus.ProtocolError)
                {
                    errors.Add(new FsItem("ProtocolError", "", false, -1));
                }
                return errors;
            }
            FtpWebRequest namesreq = (FtpWebRequest)FtpWebRequest.Create(hostdestination);
            namesreq.Credentials = new NetworkCredential(user, password);
            namesreq.Method = WebRequestMethods.Ftp.ListDirectory;
            namesreq.Timeout = 10000;
            StreamReader namesreader ;
            try
            {
               namesreader = new StreamReader(namesreq.GetResponse().GetResponseStream());
            }
            catch
            {
                return new List<FsItem>();
            }
            List<FsItem> a = new List<FsItem>();
            FsItem mainItem = new FsItem();
            mainItem.Path = hostdestination;
            mainItem.IsFolder = true;

            FsItem backItem = new FsItem();
            hostdestination = hostdestination.Replace("ftp://", "");
            int trim = hostdestination.LastIndexOf('/');
            if (trim != -1) backItem.Path = "ftp://" + hostdestination.Remove(trim);
            else backItem.Path = "ftp://" + hostdestination;
            hostdestination = "ftp://" + hostdestination;
            a.Add(mainItem);
            a.Add(backItem);
            //string s1 = namesreader.ReadToEnd();
            //string s2 = reader.ReadToEnd();
            //string j = "";
            //return new List<FsItem>();
            while (reader.EndOfStream != true)
            {
                FsItem item = new FsItem();
                string about = reader.ReadLine();

                if (about[about.Length - 1] != '.')
                {
                    
                    item.Name = namesreader.ReadLine();
                    
                    item.Path = hostdestination + "/" + item.Name;
                    about = about.ToLower();
                    string[] aboutmas = about.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
                    int dateindex = -1;
                    for (int i = 0; i < aboutmas.Length; i++)
                    {
                        string d = aboutmas[i];
                        foreach (string m in month)
                        {
                            if (m == aboutmas[i])
                            {
                                dateindex = i;
                                break;
                            }
                        }
                        if (dateindex != -1) break;
                    }
                    if (dateindex != -1)
                    {
                        aboutmas[dateindex] = "";
                        aboutmas[dateindex + 1] = "";
                        aboutmas[dateindex + 2] = "";
                    }

                    if (about[0] == 'd')
                    {
                        item.IsFolder = true;
                    }
                    else if (about[0] == '-')
                    {
                        item.IsFolder = false;
                        foreach (string s in aboutmas)
                        {
                            if (s != "" && s.Length > 1)
                                if (IsNumber(s))
                                {
                                    item.Size = Convert.ToInt32(s);
                                    break;
                                }

                        }

                    }
                    else
                    {
                        if (about.Contains("dir") || about.Contains("directory") || about.Contains("folder"))
                        {
                            item.IsFolder = true;
                        }
                        else
                        {
                            item.IsFolder = false;
                            foreach (string s in aboutmas)
                            {
                                if (s != "" && s.Length > 1)
                                    if (IsNumber(s))
                                    {
                                        item.Size = Convert.ToInt32(s);
                                        break;
                                    }

                            }
                        }

                    }
                    a.Add(item);
                }
            }
            return a;
        }
        [WebMethod]
        public bool CheckFile(string hostdestination, string user, string password)
        {
            hostdestination = hostdestination.Replace('\\', '/');
            hostdestination = hostdestination.TrimEnd(new char[] { '/' });
            hostdestination = hostdestination.Replace("ftp://", "");
            int trim = hostdestination.LastIndexOf('/');
            string directory;
            if (trim != -1) directory = "ftp://" + hostdestination.Remove(trim);
            else directory = "ftp://" + hostdestination;
            hostdestination = "ftp://" + hostdestination;
            FtpWebRequest namesreq = (FtpWebRequest)FtpWebRequest.Create(directory);
            namesreq.Credentials = new NetworkCredential(user, password);
            namesreq.Method = WebRequestMethods.Ftp.ListDirectory;
            StreamReader namesreader = new StreamReader(namesreq.GetResponse().GetResponseStream());
            while (namesreader.EndOfStream != true)
            {
                if (hostdestination == directory + "/" + namesreader.ReadLine()) return true;
            }
            return false;
        }
        [WebMethod]
        public bool CheckDirectory(string hostdestination, string user, string password)
        {
            DirectoryInfo mainDir;
            if (hostdestination != "*")
            {
                mainDir = new DirectoryInfo(hostdestination);
            }
            else mainDir = new DirectoryInfo(Server.MapPath(""));

            return mainDir.Exists;
        }
        [WebMethod]
        public bool deleteDirectory(string hostdestination, string user, string password)
        {
            try
            {
                hostdestination = hostdestination.Replace('\\', '/');
                FtpWebRequest req = (FtpWebRequest)FtpWebRequest.Create(hostdestination);
                req.Credentials = new NetworkCredential(user, password);
                req.Method = WebRequestMethods.Ftp.RemoveDirectory;
                req.GetResponse();
                return true;
            }
            catch { return false; }
        }
        [WebMethod]
        public bool deleteFile(string hostdestination, string user, string password)
        {
            try
            {
                hostdestination = hostdestination.Replace('\\', '/');
                FtpWebRequest req = (FtpWebRequest)FtpWebRequest.Create(hostdestination);
                req.Credentials = new NetworkCredential(user, password);
                req.Method = WebRequestMethods.Ftp.DeleteFile;
                req.GetResponse();
                return true;
            }
            catch { return false; }
        }
        [WebMethod]
        public void CreateFolder(string hostdestination, string user, string password)
        {
            try
            {
                hostdestination = hostdestination.Replace('\\', '/');
                FtpWebRequest req = (FtpWebRequest)FtpWebRequest.Create(hostdestination);
                req.Credentials = new NetworkCredential(user, password);
                req.Method = WebRequestMethods.Ftp.MakeDirectory;
                req.GetResponse();
            }
            catch { }
        }
        [WebMethod]
        public void SaveFile(String hostdestination, Int32 dataLength, Byte[] data, string user, string password)
        {

            hostdestination = hostdestination.Replace('\\', '/');
            FtpWebRequest req = (FtpWebRequest)FtpWebRequest.Create(hostdestination);
            req.Credentials = new NetworkCredential(user, password);
            req.Method = WebRequestMethods.Ftp.AppendFile;
            Stream s = req.GetRequestStream();
            s.Write(data, 0, dataLength);
            s.Close();
            
            req.GetResponse();
        }
        [WebMethod]
        public void MoveItem(string hostdestination, string newpath, bool isFolder, string user, string password)
        {
            hostdestination = hostdestination.Replace('\\', '/');
            newpath = newpath.Replace('\\', '/');
            Uri newuri = new Uri(newpath);
            newpath = "../../../../../../../../../../../../../../../../../../../../../../../../../../../.." + newuri.LocalPath;

            FtpWebRequest req = (FtpWebRequest)FtpWebRequest.Create(hostdestination);
            req.Credentials = new NetworkCredential(user, password);
            req.Method = WebRequestMethods.Ftp.Rename;
            req.RenameTo = newpath;
            try
            {
                req.GetResponse();
            }
            catch { };
        }
        [WebMethod]
        public string getChunk(string hostdestination, int offset, int chunklength, string user, string password)
        {
            FtpWebRequest req = (FtpWebRequest)FtpWebRequest.Create(hostdestination);
            req.Credentials = new NetworkCredential(user, password);
            req.ContentOffset = offset;
            byte[] buffer = new byte[chunklength];
            req.GetResponse().GetResponseStream().Read(buffer, 0, chunklength);

            return buffer[0].ToString() + " " + buffer[1].ToString() + " " + buffer[2].ToString() + " " + buffer[3].ToString();
        }
        [WebMethod]
        public byte[] downloadFile(string hostdestination, int offset, int chunklength, string user, string password)
        {
            hostdestination = hostdestination.Replace('\\', '/');
            hostdestination = hostdestination.TrimEnd(new char[] { '/' });
            FtpWebRequest req = (FtpWebRequest)FtpWebRequest.Create(hostdestination);
            req.Credentials = new NetworkCredential(user, password);
            req.ContentOffset = offset;
            WebResponse wr = req.GetResponse();
            Stream fs = wr.GetResponseStream();
            Int32 bytesRead = 0;
            byte[] buffer = new byte[chunklength];
            bytesRead = fs.Read(buffer, 0, chunklength);
            req.Abort();
            if (bytesRead != 0)
            {
                byte[] realbuffer = new byte[bytesRead];
                for (int i = 0; i < bytesRead; i++)
                {
                    realbuffer[i] = buffer[i];
                }

                return realbuffer;
            }
            else
            {

                return null;
            }
        }
        public bool IsNumber(String strNumber)
        {
            Regex objIsNumberPattern = new Regex("[0-9]*");
            return objIsNumberPattern.Match(strNumber).Length == strNumber.Length;
        }
    }
}
